#ifndef __KERNEL_OFS__
#define __KERNEL_OFS__

#include "directory.h"
#include "kpath.h"
#include "section.h"

namespace xm
{
	enum 
	{
		OFS_CREATE_DIR = 1,
		OFS_WIN32_PATH = 2,			// . | .. | 
		OFS_NO_NAME_CHECK = 0x10,
		OFS_BUILDIN = 0x20,
		OFS_CREATE_SHARE = 0x40,
	};

	enum rpr_t
	{
		NS_FAIL			= -1,
		NS_WIN32_UNK	= 0,
		NS_WIN32_FILE	= 1,
		NS_WIN32_DEV	= 2,
		NS_WIN32_UNC	= 3,
		NS_NT_ROOT		= 10,
	};

	template < size_t PAGE_COUNT >
	class RoVmPages : public IKBStream, UnkBase
	{
	protected:

		uint8_t		_pages[PAGE_COUNT*VM_PAGE_SIZE];
		uint64_t	_pointer;

		enum { this_length = PAGE_COUNT*VM_PAGE_SIZE };

	public:

		UNKNOWN_IMP1(IKBStream);

		RoVmPages() : _pointer(0)
		{
			memset( _pages, 0, this_length );
		}

		template < class T >
		T * get_as_ptr()
		{
			return (T*)_pages;
		}

		STDMETHOD_(BOOL,IsVirtual)() { return TRUE; };

		STDMETHOD(Read)( LPVOID lpBuffer, SIZE_T cbData, SIZE_T * lpEff )
		{
			return Readp( _pointer, lpBuffer, cbData, lpEff );
		}
		STDMETHOD(Write)( LPCVOID lpBuffer, SIZE_T cbData, SIZE_T * lpEff )
		{
			return E_ACCESSDENIED;
		}
		STDMETHOD(Seek)( INT64 liDistance, SEEK_FORM emFrom )
		{
			if( emFrom == FROM_BEGIN )
				_pointer = liDistance;
			else if( emFrom == FROM_CUR )
				_pointer += liDistance;
			else if( emFrom == FROM_END )
				_pointer = this_length + liDistance;
			else
				return E_INVALIDARG;
			return S_OK;
		}
		STDMETHOD(Tell)( UINT64 * puliPointer )
		{
			*puliPointer = _pointer;
			return S_OK;
		}
		STDMETHOD(Readp)( UINT64 uliPos, LPVOID lpBuffer, SIZE_T cbData, SIZE_T * lpEff )
		{
			if( lpEff ) *lpEff = 0;
			if( uliPos >= this_length ) 
				return S_OK;
			size_t off = (size_t)uliPos;
			size_t want = this_length - off;
			want = MIN(want, cbData);
			memcpy( lpBuffer, _pages + off, want );
			if( lpEff ) *lpEff = want;
			_pointer += uliPos + want;
			return S_OK;
		}
		STDMETHOD(Writep)( UINT64 uliPos, LPCVOID lpBuffer, SIZE_T cbData, SIZE_T * lpEff )
		{
			return E_ACCESSDENIED;
		}
		STDMETHOD(SetPos)( UINT64 uliPos )
		{
			_pointer = uliPos;
			return S_OK;
		}
		STDMETHOD_(UINT64,Length)()
		{
			return this_length;
		}
		STDMETHOD(Truncate)()
		{
			return E_ACCESSDENIED;
		}

	};

	typedef RoVmPages<1>		shared_t;

	class ntcore_t
	{
	protected:
		optr<directory_t>		_nt_root;
		optr<directory_t>		_w32_root;
		optr<directory_t>		_dev_root;
		optr<directory_t>		_bno_root;
		optr<volume_t>			_os_volume;
		optr<volume_t>			_dos_volmes[26];
		//////////////////////////////////////////////////////////////////////////
		// minicore
		optr<section_t>			_mc_sect;
		optr<imagex_t>			_mc_image;
		//////////////////////////////////////////////////////////////////////////
		// usr_shared_data
		optr<section_t>			_kusr_shdat;		// _KUSER_SHARED_DATA
		optr<shared_t>			_shared_data;		
	protected:
		std::vector< kop_t >	_holder;
	public:
		const char *			os_drive();
		volume_t *				os_volume();
		section_t*				mc_section( size_t is64 );
		imagex_t*				mc_image( size_t is64 );
		section_t*				shared_data_section();
	public:
		ntcore_t();
		long					init( char sysdrive, xv::xvalue_t & exi );
		directory_t *			ntspace();
		directory_t *			w32space();
		directory_t *			devspace();
		directory_t	*			bnospace();
		kop_t					find_path( const char * path, size_t opt );
		kop_t					find_path( w32_path_t& path, size_t opt = 0 );
		kop_t					find_path( nt_path_t& path, size_t opt = 0 );
		optr<directory_t>		create_directory( size_t opt, const char * path );
		long					mount_object( size_t opt, const char * path, kip_t obj );
		long					mount_object( w32_path_t& path, kip_t obj );
		long					mount_object( nt_path_t& path, kip_t obj );
		optr<symbol_link_t>		create_link( size_t opt, const char * path, const char * name, const char * nt_target );
		optr<volume_t>			create_volume( size_t volid, size_t opt );
		optr<symbol_link_t>		map_dos_volume( char ch, volume_t * pvol, size_t opt );
		optr<volm_file_t>		create_file( size_t opt, const char * path, const char * name );
	protected:
		kop_t					find_xx_path( directory_t * from, b_path_t& name, size_t opt );
		long					mount_xx_object( directory_t * from, b_path_t& path, kip_t obj, size_t opt );
		void					hold_buildin( kip_t ko );

	public:

		rpr_t					resolve_path_win32( const char * anypath, w32_path_t & ret );

	protected:

		typedef	std::map< std::string, optr<section_t> > section_map_t;

		section_map_t			_sect_map;

	public:

		long					put_section( section_t * secp );
		optr<section_t>			get_section( const char * full );
		optr<section_t>			get_section( std::string& full );
		long					del_section( std::string& full );
		long					del_section( const char * full );

	protected:

		long					nativ_img_load( LPCSTR dllname, optr<section_t> & sect );


	};
};


#endif